/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.sonar.util.ui.mon;

import bgu.sonar.util.buffers.BlockingByteBuffer;
import java.awt.Image;
import java.io.InputStream;
import java.io.PrintStream;
import org.openide.util.ImageUtilities;

/**
 *
 * @author bennyl
 */
public class SimpleMonitor implements Monitor {

    public static final Image BASE_ICON = ImageUtilities.loadImage("resources/img/application-monitor.png");
    private double progress;
    private BlockingByteBuffer bbbuf = new BlockingByteBuffer();
    private boolean closed = false;
    private String name;
    private Image icon = null;

    public SimpleMonitor(String name, Image icon) {
        this.name = name;
        this.icon = icon;
    }

    public SimpleMonitor(String name) {
        this(name, BASE_ICON);
    }

    @Override
    public InputStream getInputStream() {
        return bbbuf.wrappingInputStream(-1);
    }

    @Override
    public synchronized void write(String what) {
        bbbuf.write(what.getBytes());
    }

    /**
     * atomically increase progress
     *
     * @param amount
     */
    @Override
    public synchronized void incProgress(double amount) {
        progress = Math.min(1, amount + progress);
    }

    @Override
    public double getProgress() {
        return progress;
    }

    @Override
    public Monitor sub(final double p) {
        final SimpleMonitor othis = this;
        SimpleMonitor s = new SimpleMonitor(name) {
            @Override
            public synchronized void incProgress(double amount) {
                double oldProgress = super.getProgress();
                super.incProgress(amount);
                othis.incProgress(getProgress() * p - oldProgress * p);
            }

            @Override
            public synchronized void setProgress(double progress) {
                double oldProgress = super.getProgress();
                super.setProgress(progress);
                othis.setProgress(othis.getProgress() - (oldProgress * p) + progress * p);
            }

            @Override
            public void close() {
                this.incProgress(1);
                super.close();
            }
        };
        s.bbbuf = this.bbbuf;
        return s;
    }

    @Override
    public String readAvailableInput() {
        return new String(bbbuf.readAvailable());
    }

    @Override
    public void close() {
        this.closed = true;
        this.progress = 1;
    }

    @Override
    public boolean isClosed() {
        return this.closed;
    }

    @Override
    public synchronized void setProgress(double progress) {
        this.progress = Math.min(1, progress);
    }

    @Override
    public String getVisualName() {
        return name;
    }

    @Override
    public Image getIcon() {
        return icon;
    }

    @Override
    public void writeln(String what) {
        write(what + "\n");
    }

    @Override
    public void writeln(String what, double processIncrement) {
        writeln(what);
        incProgress(processIncrement);
    }

    public void redirectOutput(PrintStream out) {
        bbbuf.redirectOutput(out);
    }

    @Override
    public String getDescription() {
        return "";
    }
}
